use walkdir::WalkDir;

use super::path_item::PathAttribute;


pub fn list_filenames(file_pattern: &str) -> Vec<(String, String)> {
    // 如: file_pattern = "/var/hzs/data/stock/tick_sz/20230516/*.log"
    let mut list_filename_filepath = vec![];

    for entry in glob::glob(&file_pattern).expect("Failed to read glob pattern") {
        match entry{
            Ok(full_path) => {
                match full_path.file_name() {
                    Some(file_name) => {
                        let file_name = file_name.to_str().unwrap_or("unreachable").to_string();
                        let full_path = full_path.to_str().unwrap_or("unreachable").to_string();
                        list_filename_filepath.push((file_name, full_path));
                    },
                    None => unreachable!(),
                }
            },
            Err(_) => continue,
        }
    }
    list_filename_filepath

}


pub fn list_directory(dir_in: &str, max_depth: usize) -> Vec<PathAttribute> {
    let wd = WalkDir::new(dir_in).max_depth(max_depth).sort_by_file_name();
    let mut list_path = vec![];

    for entry in wd {
        match entry {
            Ok(v) => {
                match PathAttribute::from_direntry(dir_in, v) {
                    Ok(p) => list_path.push(p),
                    Err(e) => error!("path_io::list_directory error: {e:?}."),
                }
            },
            Err(e) => error!("path_io::list_directory: get entry error {e:?}."),
        }
    }
    list_path

}
#[test]
fn test_list_directory() {
    let dir_in = "X:/data/stock/static/20210517";
    let list_path = list_directory(dir_in, 3);
    for path in list_path.iter() {
        println!("{}", path.to_print());
    }
}



pub fn is_file(file: &str) -> bool {
    let path = std::path::Path::new(file);
    path.is_file()
}
pub fn is_dir(dir_in: &str) -> bool {
    let path = std::path::Path::new(dir_in);
    path.is_dir()
}

pub fn remove_file(file: &str) -> String {
    let path = std::path::Path::new(file);
    if !path.is_file() {
        return format!("文件删除失败：不存在！{file}");
    }

    match std::fs::remove_file(path) {
        Ok(_) => format!("文件删除成功：{file}"),
        Err(e) => format!("文件删除失败：{file}, {:?}", e),
    }
}

/// 仅适用于：文件和文件夹
pub fn rename(dir_parent: &str, name_old: &str, name_new: &str) -> bool {
    let file_old = format!("{dir_parent}/{name_old}");
    let path_old = std::path::Path::new(&file_old);
    if !path_old.is_file() && !path_old.is_dir() {
        println!("path_io::rename: 不是文件也不是文件夹");
        return false;
    }
    let file_new = format!("{dir_parent}/{name_new}");

    match std::fs::rename(file_old, &file_new) {
        Ok(_) => true,
        Err(e) => {
            println!("path_io::rename: {e:?}");
            false
        },
    }

}



pub fn ensure_dir(dir_in: &str) -> String {
    match std::fs::create_dir_all(dir_in) {
        Ok(_) => format!("true: 文件夹 {dir_in} 创建成功！"),
        Err(e) => format!("false: 文件夹 {dir_in} 创建失败！{e:?}"),
    }
}
/// 确保父文件夹存在
pub fn ensure_parent_dir(dir_or_file: &str) -> String {
    let path = std::path::Path::new(dir_or_file);
    if path.is_file() {
        return format!("true, ensure_parent_dir: 文件已存在！{dir_or_file}");
    }
    if path.is_dir() {
        return format!("true, ensure_parent_dir: 文件夹已存在！{dir_or_file}");
    }
    match path.parent() {
        Some(v) => {
            if v.is_dir() {
                return format!("true, ensure_parent_dir: {dir_or_file}的父文件夹 已存在！");
            }
            match std::fs::create_dir_all(v) {
                Ok(_) => return format!("true, ensure_parent_dir: {dir_or_file}的父文件夹 创建成功！"),
                Err(e) => return format!("false, ensure_parent_dir: {dir_or_file}的父文件夹 创建失败！{e:?}"),
            }
        },
        None => return format!("false, ensure_parent_dir: {dir_or_file}的父文件夹 不存在！"),
    }
}

#[test]
fn test_ensure_parent_dir() {
    let msg =  ensure_parent_dir("d:/temp/202410/1/2/20241006.sqlite");
    println!("{msg}");
}

/// >=0: 文件; -1: 文件夹; -2: 其他
pub fn file_size(file: &str) -> i64 {
    match std::fs::metadata(file) {
        Ok(v) => {
            if v.is_file() {
                v.len() as i64
            } else if v.is_dir() {
                -1
            } else {
                -2
            }
        },
        Err(_) => -2,
    }
}

